package com.ffs.fsm;

import com.ffs.fsm.action.*;

import java.util.ArrayList;
import java.util.List;

/**
 * 状态机
 *
 * @author fengfasong
 * @date 2021/4/24
 */
public class FSMMachine {


    /**
     * 状态转移表
     */
    private static List<ActionMapping> mappings = new ArrayList<>();

    static {
        //空闲，登录请求，成功
        mappings.add(ActionMapping.ofMap(State.WAIT_LOGIN, Event.LOGIN_SUCCESS, State.SUCCESS, new LoginSuccessAction()));
        //空闲，登录请求，失败
        mappings.add(ActionMapping.ofMap(State.WAIT_LOGIN, Event.LOGIN_FAIL, State.REFUSED, new LoginFailAction()));

        /**
         * 登录逻辑
         */
        //创建角色登录
        mappings.add(ActionMapping.ofMap(State.init, Event.InitScene, State.login, new LoginSuccessAction()));
        mappings.add(ActionMapping.ofMap(State.login, Event.LoginScene, State.select_roles, new SelectRoleAction()));
        mappings.add(ActionMapping.ofMap(State.select_roles, Event.SelectRoleScene, State.readyGameState, new ReadyGameAction()));

        //创建角色
        mappings.add(ActionMapping.ofMap(State.init, Event.InitScene, State.login, new LoginSuccessAction()));
        mappings.add(ActionMapping.ofMap(State.login, Event.RandomNameScene, State.random_name, new RandomNameAction()));
        mappings.add(ActionMapping.ofMap(State.random_name, Event.RandomNameScene, State.create_role_single, new CreateRoleSingleAction()));

        //登录角色
        mappings.add(ActionMapping.ofMap(State.init, Event.InitScene, State.login, new LoginSuccessAction()));
        mappings.add(ActionMapping.ofMap(State.login, Event.LoginScene, State.select_roles, new SelectRoleAction()));
        mappings.add(ActionMapping.ofMap(State.select_roles, Event.SelectRoleScene, State.readyGameState, new ReadyGameAction()));
    }

    /**
     * 状态切换
     *
     * @param currentState 当前状态
     * @param event        事件
     * @param context      上下文参数
     * @return 状态切换成功
     */
    public boolean transform(State currentState, Event event, Context context) {
        ActionMapping actionMapping = getMapping(currentState, event);
        if (null == actionMapping) {
            throw new RuntimeException("未找到相应的要素映射");
        }
        Action action = actionMapping.getAction();
        action.action(context);
        return true;
    }

    /**
     * 获取映射
     *
     * @param currentState 当前状态
     * @param event        事件
     * @return 要素映射
     */
    private ActionMapping getMapping(State currentState, Event event) {
        if (mappings.size() > 0) {
            for (ActionMapping n : mappings) {
                if (n.getCurrentState().equals(currentState) && n.getEvent().equals(event)) {
                    return n;
                }
            }
        }
        return null;
    }
}
